package com.hooya.fa.eu.biz.dao.manager;

import com.hooya.fa.eu.api.enums.PlInvoiceTypeEnum;
import com.hooya.fa.eu.api.feign.RemoteThirdPtService;
import com.hooya.fa.eu.biz.dao.entity.PlInvoice;
import com.hooya.fa.eu.biz.dao.entity.PlInvoiceRecord;
import com.hooya.integrated.common.core.util.DoubleUtil;
import com.hooya.integrated.common.core.util.R;
import com.hooya.integrated.thirdpt.api.dto.*;
import com.hooya.integrated.thirdpt.api.vo.InvoicingAppendVO;
import com.hooya.integrated.thirdpt.api.vo.InvoicingResultVO;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 1
 * @Author : Zongz
 * @Copyright Copyright (c) 豪雅集团
 * @Create 2024/6/17
 * @Version 1.0.0
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PlInvoiceManager {

    private final RemoteThirdPtService remoteThirdPtService;

    /**
     * 处理发票详情
     *
     * @param records   明细
     * @param positions 集合
     * @param l         发票信息
     * @param first     是否首次
     */
    public void dealWithInvoiceRecord(List<PlInvoiceRecord> records, List<InvoicePosition> positions,
                                      PlInvoice l, boolean first) {
        log.info("本次发票数量：" + records.size());
        XxlJobHelper.log("本次发票数量：" + records.size());
        //发票条目明细
        for (PlInvoiceRecord record : records) {
            InvoicePosition position = new InvoicePosition();
            position.setName(record.getSku() + "_" + record.getDescription());
            position.setQuantity(record.getQty());
            position.setTax(l.getTax());
            position.setTotal_price_gross(record.getTotalPriceGross());
            positions.add(position);
        }
        //运费
        if (l.getDeliveryCharge().compareTo(0D) != 0 && first) {
            InvoicePosition position = new InvoicePosition();
            position.setName("Delivery charge");
            position.setQuantity(1);
            position.setTax(l.getTax());
            position.setTotal_price_gross(l.getDeliveryCharge());
            positions.add(position);
        }
    }

    /**
     * 新增PL发票
     *
     * @param add   发票
     * @param plIds 波兰发票id列表
     * @return InvoicingResultVO
     */
    public InvoicingResultVO addPLInvoiceInfo(InvoiceDTO add, List<Integer> plIds) {
        try {
            //log
            R<InvoicingResultVO> res = remoteThirdPtService.addInvoice(add);
            InvoicingResultVO invoicingRes = res.getData();
            Thread.sleep(300);
            log.info("pl_id: " + invoicingRes.getId());
            XxlJobHelper.log("pl_id: " + invoicingRes.getId());
            plIds.add(invoicingRes.getId());
            return invoicingRes;
        } catch (Exception e) {
            //删除PL发票API
//                batchDeletePlInvoice(plIds);
            log.error(e.getMessage());
            XxlJobHelper.log("新增失败，原因: {} ,立即删除！", e.getMessage());
            deletePlInvoiceByNumber(add.getInvoice().getNumber());
//                throw new RuntimeException("添加发票失败，失败原因：" + e.getMessage());
        }
        return null;
    }


    /**
     * 回写本地发票内容
     *
     * @param invoicingRes     结果
     * @param records          详情
     * @param updateRecordData 更新对象
     */
    public void writeBackRecord(InvoicingResultVO invoicingRes, List<PlInvoiceRecord> records,
                                List<PlInvoiceRecord> updateRecordData) {
        Map<String, PlInvoiceRecord> invoiceRecordMap = records.stream()
                .collect(Collectors.toMap(PlInvoiceRecord::getSku, i -> i));
        for (InvoicingAppendVO appendVO : invoicingRes.getPositions()) {
            PlInvoiceRecord record = invoiceRecordMap.get(appendVO.getName().split("_")[0]);
            // 回写开票的信息，运费无需回写
            if (Objects.nonNull(record)) {
                writeRecord(record, appendVO);
                updateRecordData.add(record);
            } else if (appendVO.getName().equals("Delivery charge")) {
                record = new PlInvoiceRecord();
                writeRecord(record, appendVO);
                record.setInvoiceId(records.get(0).getInvoiceId());
                record.setSku(appendVO.getName());
                record.setQty(1);
                record.setTotalPriceGross(record.getPlTotalPriceGross());
                updateRecordData.add(record);
            }
        }
    }

    //抽离明细回写
    private void writeRecord(PlInvoiceRecord record, InvoicingAppendVO appendVO) {
        record.setPlInvoiceId(appendVO.getInvoice_id());
        record.setPlInvoiceDtlId(appendVO.getId());
        record.setPlQty((int) Double.parseDouble(appendVO.getQuantity()));
        record.setPlTotalPriceTax(Double.parseDouble(appendVO.getTotal_price_tax()));
        record.setPlTotalPriceNet(Double.parseDouble(appendVO.getTotal_price_net()));
        record.setPlTotalPriceGross(Double.parseDouble(appendVO.getTotal_price_gross()));
    }

    /**
     * 根据id更新发票
     *
     * @param plId   波兰发票id
     * @param update 更新内容
     * @return InvoicingResultVO
     */
    public InvoicingResultVO updatePLInvoiceInfo(Integer plId, InvoiceUpdateDTO update) {
        try {
            R<InvoicingResultVO> updatedInvoiceRes = remoteThirdPtService.updateInvoice(plId, update);
            Thread.sleep(300);
            return updatedInvoiceRes.getData();
        } catch (Exception e) {
            XxlJobHelper.log("更新失败，原因: {} ,立即删除！", e.getMessage());
            log.error(e.getMessage());
            batchDeletePlInvoice(Collections.singletonList(plId));
        }
        return null;
    }

    /**
     * 根据id删除发票
     *
     * @param plIds 波兰发票id列表
     */
    public void batchDeletePlInvoice(List<Integer> plIds) {
        if (CollectionUtils.isEmpty(plIds)) {
            return;
        }
        for (Integer id : plIds) {
            R<String> res = remoteThirdPtService.deleteInvoice(id);
            log.info("发票id【" + id + "】删除结果：" + res.getData());
        }
    }

    public InvoicingResultVO getInvoiceById(Integer plId) {
        R<InvoicingResultVO> res = remoteThirdPtService.getInvoiceById(plId);
        return res.getData();
    }

    public void deletePlInvoiceByNumber(String invoiceNumber) {
        R<InvoicingResultVO> plInvoice = remoteThirdPtService.getInvoiceByNumber(invoiceNumber);
        if (Objects.isNull(plInvoice.getData())) {
            log.info("跳过发票号：" + invoiceNumber);
            return;
        }
        R<String> res = remoteThirdPtService.deleteInvoice(plInvoice.getData().getId());
        log.info("发票id【" + plInvoice.getData().getId() + "】删除结果：" + res.getData());
    }

    public List<InvoicingResultVO> getInvoiceList(List<Integer> ids) {
        R<List<InvoicingResultVO>> res = remoteThirdPtService.getInvoiceList(ids);
        if (CollectionUtils.isEmpty(res.getData())) {
            throw new RuntimeException("波兰发票id有误" + ids);
        }
        return res.getData();
    }

    public InvoicingResultVO addCorrectionInvoiceInfo(CorrectionInvoiceDTO add) {
        try {
            //log
            R<InvoicingResultVO> res = remoteThirdPtService.addInvoiceCorrection(add);
            InvoicingResultVO invoicingRes = res.getData();
            Thread.sleep(300);
            log.info("pl_id: " + invoicingRes.getId());
            XxlJobHelper.log("pl_id: " + invoicingRes.getId());
            return invoicingRes;
        } catch (Exception e) {
            //删除PL发票API
//                batchDeletePlInvoice(plIds);
            log.error(e.getMessage());
//                throw new RuntimeException("添加发票失败，失败原因：" + e.getMessage());
        }
        return null;
    }

    public List<CorrectionInvoicePositionDTO> dealWithCorrectionInvoicePosition(PlInvoice correction, List<String> skuList,
                                                                                Map<String, PlInvoiceRecord> originSkuMap,
                                                                                Map<String, PlInvoiceRecord> correctionSkuMap,
                                                                                List<CorrectionInvoicePositionDTO> addPositions) {
        List<CorrectionInvoicePositionDTO> curPosition = new LinkedList<>();
        for (String sku : skuList) {
            PlInvoiceRecord originSkuRecord = originSkuMap.get(sku);
            PlInvoiceRecord correctionSkuRecord = correctionSkuMap.get(sku);
            Integer tax = correction.getTax();
            CorrectionAttributesDTO before = CorrectionAttributesDTO.builder().kind("correction_before")
                    .total_price_gross(0D).quantity(0).tax(tax).build();
            CorrectionAttributesDTO after = CorrectionAttributesDTO.builder().kind("correction_after")
                    .total_price_gross(0D).quantity(0).tax(tax).build();
            String name = sku;
            if (Objects.nonNull(originSkuRecord)) {
                name = sku + "_" + originSkuRecord.getDescription();
                before.setQuantity(originSkuRecord.getQty());
                before.setTotal_price_gross(originSkuRecord.getTotalPriceGross());
            }
            if (Objects.nonNull(correctionSkuRecord)) {
                name = sku + "_" + correctionSkuRecord.getDescription();
                after.setQuantity(correctionSkuRecord.getQty());
                after.setTotal_price_gross(correctionSkuRecord.getTotalPriceGross());
            }
            before.setName(name);
            after.setName(name);
            CorrectionInvoicePositionDTO position = CorrectionInvoicePositionDTO.builder().tax(tax).name(name)
                    .kind(PlInvoiceTypeEnum.CORRECTION.getValue()).quantity(after.getQuantity() - before.getQuantity())
                    .total_price_gross(DoubleUtil.sub(after.getTotal_price_gross(), before.getTotal_price_gross()))
                    .correction_before_attributes(before).correction_after_attributes(after).build();
            curPosition.add(position);
        }
        addPositions.addAll(curPosition);
        return curPosition;
    }

    public InvoicingResultVO updateCorrectionInvoiceInfo(Integer plId, CorrectionInvoiceUpdateDTO update) {
        try {
            //log
            R<InvoicingResultVO> res = remoteThirdPtService.updateInvoiceCorrection(plId, update);
            Thread.sleep(100);
            return res.getData();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 新增运费条目
     *
     * @param origin       原始发票
     * @param correction   修正发票
     * @param addPositions 发票明细
     */
    public void addDeliveryCharge(PlInvoice origin, PlInvoice correction, List<CorrectionInvoicePositionDTO> addPositions) {
        Integer tax = correction.getTax();
        String name = "Delivery charge";
        CorrectionAttributesDTO before = CorrectionAttributesDTO.builder().kind("correction_before").name(name)
                .total_price_gross(origin.getDeliveryCharge()).quantity(1).tax(origin.getTax()).build();
        CorrectionAttributesDTO after = CorrectionAttributesDTO.builder().kind("correction_after").name(name)
                .total_price_gross(correction.getDeliveryCharge()).quantity(1).tax(tax).build();
        CorrectionInvoicePositionDTO position = CorrectionInvoicePositionDTO.builder().tax(tax).name(name)
                .kind(PlInvoiceTypeEnum.CORRECTION.getValue()).quantity(after.getQuantity() - before.getQuantity())
                .total_price_gross(DoubleUtil.sub(after.getTotal_price_gross(), before.getTotal_price_gross()))
                .correction_before_attributes(before).correction_after_attributes(after).build();
        addPositions.add(position);
    }
}
